TerraformのChecksとTestsの使い分け
「ChecksとTestsはどう違うのか?」
Terraformのコード検証やテストの方法として、ChecksとTestsがあります。
どう違ってどう使い分ければ良いのか疑問に思ったため、まとめてみます。
結論
結論からです。TestsとChecksの概要から知りたい方は、「ChecksとTestsの概要」から読んでもらえればと思います。
TestsとChecksの大きな違いは以下かと思います。
- テスト用の一時的なリソース作成の有無
- ライフサイクルの外側でのチェックの有無
以下の使い分けをお勧めします。
- Terraformのライフサイクル管理外のテストは、Checks
- モジュールに対するテストは、Tests
- | Tests | Checks |
---|---|---|
テスト用の一時的なリソース作成 | ◯ | - |
ライフサイクルの外側でのチェック | △ | ◯ |
実行のタイミング | terraform test | terraform plan/apply時 |
記述方法 | test.hclファイル | tfファイル内 |
1. テスト用の一時的なリソース作成の有無
Testsはテスト実行時に、テスト用のリソースを一時的に作成することができます。
上記の何が嬉しいかというと、直接リソースを作成しない(※)モジュールでテストが行いやすいです。
tfファイルを直接みる静的解析に比べて、ApplyやPlanを伴うテストの方が得られる情報は多いため踏み込んだテストができます。
呼び出し側でテストをする場合、関連するリソースの数が多く1回あたりの実行に時間がかかります。
全体に比べて作成するリソース数が少ないため、Testsはモジュール単位でテストを行うことに適しています。
※ディレクトリで直接terraform apply
を行わない。他tfファイルから呼び出して、リソースを作成する。
2. ライフサイクルの外側でのチェックの有無
Terraformの設定ファイルだけでは、ステータスがわからない項目もあります。
例えば、
- AWS Budgetsの予算を超過していないか
- ACMでインポートした証明書の有効期限は切れていないか
上記の項目のチェックには、Checksを利用できます。
逆にTestsで上記を確認しようとすると、コマンドを別で叩く必要がある・Stateファイルも別になるため手間やテストの実行時間が伸びます。
ChecksとTestsの概要
Checks
terraform 1.5で追加された機能です。
Terraformで作成したインフラストラクチャ全体に対して、ライフサイクル範囲外に対してもチェックが可能です。
例えば、以下のようにACMで証明書をインポートするとします。
resource "aws_acm_certificate" "cert" { private_key = tls_private_key.example.private_key_pem certificate_body = tls_self_signed_cert.terramino.cert_pem }
証明書のステータスを確認して、意図せずアプリへのHTTPSでの接続ができなくなる事態を防ぎたいです。
ステータスの部分は証明書の有効期限が切れる等、Terraformのライフサイクル範囲外で決まります。
aws_acm_certificate.cert.status
でステータスが取れるため、手動でやる場合はOutputに出して確認すれば良さそうです。
Checksを利用することで、terraform plan/apply
時に自動でチェックできます。
Checksは通常のtfファイル内に記述可能で、Check失敗時もPlanやApplyの実行できます。
check "certificate" { assert { condition = aws_acm_certificate.cert.status == "ISSUED" error_message = "Certificate status is ${aws_acm_certificate.cert.status}" } }
具体的な使い方の例としては、以下があります。
- AWS Budgetsで目標金額を超えていないか
- GuardDutyで脅威が検出されていないか
- IAMロールがX日以上が未使用な状態になっていないか
Checks - Configuration Language | Terraform | HashiCorp Developer
Tests
terraform 1.6で追加された機能です。
terratestやkitchen-terraformのように、統合テストやユニットテストが可能です。
terraform test
コマンドでテストを実行します。(planやapply時には実行されない)
一時的なリソースを作成し(※)、そのリソースに対してテストを行うため、既存のリソースやStateファイルに影響はありません。
例えば、S3バケットを作成するモジュールに対して、以下のようなテストが可能です。
- S3バケットの名前が正しいか
- ローカルのファイルとTerraformでアップロードしたファイル(S3オブジェクト)が同一か
テストはHCLで記述可能で、.tftest.hcl
という拡張子にする必要があります。
# Call the setup module to create a random bucket prefix run "setup_tests" { module { source = "./tests/setup" } } # Apply run block to create the bucket run "create_bucket" { variables { bucket_name = "${run.setup_tests.bucket_prefix}-aws-s3-website-test" } # Check that the bucket name is correct assert { condition = aws_s3_bucket.s3_bucket.bucket == "${run.setup_tests.bucket_prefix}-aws-s3-website-test" error_message = "Invalid bucket name" } # Check index.html hash matches assert { condition = aws_s3_object.index.etag == filemd5("./www/index.html") error_message = "Invalid eTag for index.html" } # Check error.html hash matches assert { condition = aws_s3_object.error.etag == filemd5("./www/error.html") error_message = "Invalid eTag for error.html" } }
hashicorp-education/learn-terraform-testから引用
※ ブロック内でcommand= plan
を設定しておけば、一時的にリソース作成せずにテストすることも可能
Write Terraform Tests | Terraform | HashiCorp Developer
Terraform Cloudの関連機能
Terraform Cloudの関連機能もみてみましょう。
Checks: Continuous validation
Checksは、PlanとApply時に評価されます。
証明書の有効期限やAWS Budgetsの金額は日々変わるため、Checkが失敗したらすぐ気づきたいです。
そんな時に便利なのが、「Continuous validation」です。
名前の通り、継続的にChecks等のバリデーションを評価してくれる機能です。
Terraform Cloudから通知を送ることも可能で、Check失敗時にSlack等にメッセージを送ることができます。
Health - Terraform Cloud | Terraform | HashiCorp Developer
Tests: Generated module tests
Testsは便利な機能ですが、Test自体の作成やワークフローを整備するのが面倒だったりします。
Terraform Cloudの「Generated module tests」を使えば、簡単です。
Terraform CloudのPrivate Registryに登録したモジュールに対して、テストを自動生成することが可能です。
Terraform Cloud側で、自動生成したテストを使って新しいバージョン公開時にテストを実行します。
Testing Private Modules - Private Registry - Terraform Cloud | Terraform | HashiCorp Developer
Terraform Cloudのプライベートモジュールのテスト機能とテスト自動生成を試してみた | DevelopersIO
おわりに
TestsとChecksについてでした。
それぞれの機能の概要と、使い分けのイメージがついたら幸いです。
「参考」にそれぞれのチュートリアルのリンクを貼っています。興味があったら、ぜひ試してみてください。
以上、AWS事業本部の佐藤(@chari7311)でした。